package com.bocloud.cmp.driver.providers.ali;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.rds.model.v20140815.CreateDBInstanceRequest;
import com.aliyuncs.rds.model.v20140815.CreateDBInstanceResponse;
import com.aliyuncs.rds.model.v20140815.DeleteDBInstanceRequest;
import com.aliyuncs.rds.model.v20140815.DeleteDBInstanceResponse;
import com.aliyuncs.rds.model.v20140815.DescribeDBInstanceAttributeRequest;
import com.aliyuncs.rds.model.v20140815.DescribeDBInstanceAttributeResponse;
import com.aliyuncs.rds.model.v20140815.DescribeDBInstanceAttributeResponse.DBInstanceAttribute;
import com.aliyuncs.rds.model.v20140815.DescribeDBInstancesRequest;
import com.aliyuncs.rds.model.v20140815.DescribeDBInstancesResponse;
import com.aliyuncs.rds.model.v20140815.DescribeDBInstancesResponse.DBInstance;
import com.aliyuncs.rds.model.v20140815.ModifyDBInstanceSpecRequest;
import com.aliyuncs.rds.model.v20140815.ModifyDBInstanceSpecResponse;
import com.aliyuncs.rds.model.v20140815.RestartDBInstanceRequest;
import com.aliyuncs.rds.model.v20140815.RestartDBInstanceResponse;
import com.bocloud.cmp.driver.providers.DatabaseDriver;
import com.bocloud.cmp.model.DbInstanceModel;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.utils.DateTools;
import com.bocloud.common.utils.KeyGenerator;
import com.google.common.collect.Lists;

/**
 * 阿里云RDS操作驱动实现类
 * 
 * @author dmw
 *
 */
public class AliRdsDriver extends AliDriver implements DatabaseDriver {
	private static Logger logger = LoggerFactory.getLogger(AliRdsDriver.class);
	private static final int PAGESIZE = 100;

	/**
	 * 默认构造方法
	 */
	public AliRdsDriver() {
		super();
	}

	/**
	 * 全构造方法
	 * 
	 * @param accessKey
	 * @param secretKey
	 * @param regionId
	 */
	public AliRdsDriver(String accessKey, String secretKey, String regionId) {
		super(accessKey, secretKey, regionId);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.bocloud.emaas.butler.driver.DatabaseDriver#list()
	 */
	@Override
	public BsmResult listInstances() {
		DescribeDBInstancesRequest request = new DescribeDBInstancesRequest();
		request.setPageNumber(1);
		request.setPageSize(10);
		try {
			List<DbInstanceModel> models = Lists.newArrayList();
			DescribeDBInstancesResponse response = this.getClient().getAcsResponse(request);
			int totalCount = response.getTotalRecordCount();
			List<DBInstance> dbInstances = response.getItems();
			int totalPage = totalCount / 100 + 1;
			if (totalPage == 1) {
				for (DBInstance dbInstance : dbInstances) {
					DBInstanceAttribute attribute = getAttribute(dbInstance.getDBInstanceId());
					if (null != attribute) {
						models.add(this.convert(attribute));
					}
				}
				return new BsmResult(true, models, "success");
			}
			for (int i = 2; i <= totalPage; i++) {
				request.setPageNumber(i);
				request.setPageSize(PAGESIZE);
				response = this.getClient().getAcsResponse(request);
				dbInstances = response.getItems();
				for (DBInstance dbInstance : dbInstances) {
					DescribeDBInstanceAttributeRequest detailRequest = new DescribeDBInstanceAttributeRequest();
					detailRequest.setDBInstanceId(dbInstance.getDBInstanceId());
					DescribeDBInstanceAttributeResponse detailResponse = this.getClient().getAcsResponse(detailRequest);
					List<DBInstanceAttribute> list = detailResponse.getItems();
					if (null != list && !list.isEmpty()) {
						models.add(this.convert(list.get(0)));
					}
				}
			}
			return new BsmResult(true, models, "success");
		} catch (ClientException e) {
			logger.error("listInstances error:", e);
			return new BsmResult(false, "error");
		}
	}

	private DBInstanceAttribute getAttribute(String instanceId) {
		DescribeDBInstanceAttributeRequest detailRequest = new DescribeDBInstanceAttributeRequest();
		detailRequest.setDBInstanceId(instanceId);
		DescribeDBInstanceAttributeResponse detailResponse;
		try {
			detailResponse = this.getClient().getAcsResponse(detailRequest);
			List<DBInstanceAttribute> list = detailResponse.getItems();
			if (null == list || list.isEmpty()) {
				return null;
			}
			return list.get(0);
		} catch (ClientException e) {
			logger.error("get instance attribute error:", e);
			return null;
		}
	}

	public BsmResult createInstance(DbInstanceModel instance) {
		CreateDBInstanceRequest request = new CreateDBInstanceRequest();
		request.setRegionId(instance.getRegionId());
		request.setEngine(instance.getEngine());
		request.setEngineVersion(instance.getVersion());
		request.setDBInstanceClass(instance.getInstanceClass());
		request.setDBInstanceStorage(instance.getDisk());
		request.setDBInstanceNetType(instance.getNetType());
		String ip = "0.0.0.0/0";
		request.setSecurityIPList(ip);
		request.setPayType(instance.getPayType());
		request.setClientToken(KeyGenerator.uuid());
		request.setDBInstanceDescription(instance.getRemark());
		try {
			CreateDBInstanceResponse response = this.getClient().getAcsResponse(request);
			String instanceId = response.getDBInstanceId();
			BsmResult result = this.instanceDetail(instanceId);
			if (result.isSuccess()) {
				return new BsmResult(true, result.getData(), "success");
			} else {
				return result;
			}
		} catch (ClientException e) {
			logger.error("createInstance [{}] error:", instance.getName(), e);
			return new BsmResult(false, e.getErrMsg(), "创建数据库实例失败！");
		}
	}

	@Override
	public BsmResult removeInstance(String instanceId) {
		DeleteDBInstanceRequest request = new DeleteDBInstanceRequest();
		request.setDBInstanceId(instanceId);
		try {
			DeleteDBInstanceResponse response = this.getClient().getAcsResponse(request);
			return new BsmResult(true, response.getRequestId(), "success");
		} catch (ClientException e) {
			logger.error("remove instance [{}] error:", instanceId, e);
			return new BsmResult(false, e.getErrMsg(), "删除数据库实例失败！");
		}
	}

	@Override
	public BsmResult instanceDetail(String instanceId) {
		DescribeDBInstanceAttributeRequest request = new DescribeDBInstanceAttributeRequest();
		request.setDBInstanceId(instanceId);
		try {
			DescribeDBInstanceAttributeResponse response = this.getClient().getAcsResponse(request);
			List<DBInstanceAttribute> instanceList = response.getItems();
			if (null == instanceList || instanceList.isEmpty()) {
				return new BsmResult(false, "实例不存在！");
			} else {
				return new BsmResult(true, convert(instanceList.get(0)), "success");
			}
		} catch (ClientException e) {
			logger.error("DB Instance Error!", e);
			return new BsmResult(false, "获取实例异常！");
		}
	}

	@Override
	public BsmResult modifyInstance(DbInstanceModel instance) {
		ModifyDBInstanceSpecRequest request = new ModifyDBInstanceSpecRequest();
		request.setDBInstanceId(instance.getInstanceId());
		request.setDBInstanceStorage(instance.getDisk());
		try {
			ModifyDBInstanceSpecResponse response = this.getClient().getAcsResponse(request);
			return new BsmResult(true, response.getRequestId(), "success");
		} catch (ClientException e) {
			logger.error("modifyInstance [{}] error:", instance.getInstanceId(), e);
			return new BsmResult(false, e.getErrMsg(), "修改数据库实例规格失败！");
		}
	}

	// 数据转换
	private DbInstanceModel convert(DBInstanceAttribute attribute) {
		if (null == attribute) {
			return null;
		}
		DbInstanceModel model = new DbInstanceModel();
		model.setName(attribute.getDBInstanceId());
		model.setMaxAccount(attribute.getAccountMaxQuantity());
		model.setConnectionMode(attribute.getConnectionMode().getStringValue());
		model.setConnectionString(attribute.getConnectionString());
		model.setGmtCreate(DateTools.transfer("yyyy-MM-dd'T'HH:mmZ", attribute.getCreationTime(), "Z"));
		model.setCpu(Integer.parseInt(attribute.getDBInstanceCPU()));
		model.setInstanceClass(attribute.getDBInstanceClass());
		model.setInstanceId(attribute.getDBInstanceId());
		model.setMemory(attribute.getDBInstanceMemory().intValue());
		model.setNetType(attribute.getDBInstanceNetType().getStringValue());
		if (null == attribute.getDBInstanceStatus()) {
			model.setStatus("Creating");
		} else {
			model.setStatus(attribute.getDBInstanceStatus().getStringValue());
		}
		model.setDisk(attribute.getDBInstanceStorage());
		model.setInstanceType(attribute.getDBInstanceType().getStringValue());
		model.setMaxDB(attribute.getDBMaxQuantity().intValue());
		model.setEngine(attribute.getEngine());
		model.setVersion(attribute.getEngineVersion());
		model.setExpireTime(attribute.getExpireTime());
		model.setNetworkType(attribute.getInstanceNetworkType());
		model.setLockMode(attribute.getLockMode().getStringValue());
		model.setLockReason(attribute.getLockReason());
		model.setMaxConnection(attribute.getMaxConnections());
		model.setMaxIOPS(attribute.getMaxIOPS());
		model.setPayType(attribute.getPayType());
		model.setPort(Integer.parseInt(attribute.getPort()));
		model.setRegionId(attribute.getRegionId());
		model.setZoneId(attribute.getZoneId());
		return model;
	}

	@Override
	public BsmResult rebootInstance(String instanceId) {
		RestartDBInstanceRequest request = new RestartDBInstanceRequest();
		request.setDBInstanceId(instanceId);
		try {
			RestartDBInstanceResponse response = this.getClient().getAcsResponse(request);
			return new BsmResult(true, response.getRequestId(), "success");
		} catch (ClientException e) {
			logger.error("rebootInstance [{}] error:", instanceId, e);
			return new BsmResult(false, e.getErrMsg(), "重启数据库实例失败！");
		}
	}

}
